Summary

Row

confirmed

17,849,843

active

6,611,204 (37%)

recovered

10,553,585 (59.1%)

death

685,054 (3.8%)

Row

Cases Distribution by Type (2020-08-01)

Daily Cumulative Cases

Recovery/Death Ratio

Map

Data

About

The Coronavirus Dashboard

This Coronavirus dashboard provides an overview of the 2019 Novel Coronavirus COVID-19 (2019-nCoV) epidemic. This dashboard is built with R using the Rmakrdown framework and can easily reproduce by others. The code behind the dashboard available here

Data

The input data for this dashboard is the coronavirus R package (dev version). The data and dashboard is refreshed on a daily bases. The raw data pulled from the Johns Hopkins University Center for Systems Science and Engineering (JHU CCSE) Coronavirus repository

Packages

Deployment and reproducibly

The dashboard was deployed to Github docs. If you wish to deploy and/or modify the dashboard on your Github account, you can apply the following steps:

  • Fork the dashboard repository, or
  • Clone it and push it to your Github package
  • Here some general guidance about deployment of flexdashboard on Github page - link

For any question or feedback, you can either open an issue or contact me on Twitter.

Test

Row

Recovery and Death Rates by Country

Daily Trend

Column

New Cases - Top 15 Countries (2020-08-01)

Daily New Cases - China vs. Rest of the World

Column

Recovery and Death Rates for Countries with at Least 20000 Cases

Cases Status Update for 2020-08-01

Data

---
title: "Coronavirus Dashboard"
output: 
  flexdashboard::flex_dashboard:
    orientation: rows
    social: menu
    source_code: embed
    vertical_layout: fill
---

```{r setup, include=FALSE}
#------------------ Packages ------------------
library(flexdashboard)


`%>%` <- magrittr::`%>%`
#------------------ Parameters ------------------
# Set colors
# https://www.w3.org/TR/css-color-3/#svg-color
confirmed_color <- "purple"
active_color <- "#1f77b4"
recovered_color <- "forestgreen"
death_color <- "red"
#------------------ Data ------------------
df <- read.csv("https://raw.githubusercontent.com/RamiKrispin/coronavirus/master/csv/coronavirus.csv", stringsAsFactors = FALSE) %>%
  dplyr::mutate(country = ifelse(country == "United Arab Emirates", "UAE", country),
                country = ifelse(country == "Mainland China", "China", country),
                country = ifelse(country == "North Macedonia", "N.Macedonia", country),
                country = trimws(country),
                country = factor(country, levels = unique(country)))


df_daily <- df %>% 
  dplyr::group_by(date, type) %>%
  dplyr::summarise(total = sum(cases, na.rm = TRUE),
                   .groups = "drop") %>%
  tidyr::pivot_wider(names_from = type,
                     values_from = total) %>%
  dplyr::arrange(date) %>%
  dplyr::ungroup() %>%
  dplyr::mutate(active =  confirmed - death - recovered) %>%
  dplyr::mutate(confirmed_cum = cumsum(confirmed),
                death_cum = cumsum(death),
                recovered_cum = cumsum(recovered),
                active_cum = cumsum(active))


df_tree <- df %>%
  dplyr::group_by(country, type) %>%
  dplyr::summarise(total = sum(cases), .groups = "drop") %>%
  dplyr::mutate(type = ifelse(type == "confirmed", "Confirmed", type),
                type = ifelse(type == "recovered", "Recovered", type),
                type = ifelse(type == "death", "Death", type)) %>%
  tidyr::pivot_wider(names_from = type, values_from = total) %>%
  dplyr::mutate(Active = Confirmed - Death - Recovered) %>%
  tidyr::pivot_longer(cols = -country, names_to = "type", values_to = "total")

df_world <- df_tree %>%
  dplyr::group_by(type) %>%
  dplyr::summarise(total = sum(total), .groups = "drop") %>%
  tidyr::pivot_wider(names_from = type, values_from = total)

names(df_world) <- tolower(names(df_world))

```

Summary
=======================================================================
Row
-----------------------------------------------------------------------

### confirmed {.value-box}

```{r}

valueBox(value = paste(format(df_world$confirmed, big.mark = ","), "", sep = " "), 
         caption = "Total Confirmed Cases", 
         icon = "fas fa-user-md", 
         color = confirmed_color)
```


### active {.value-box}

```{r}
valueBox(value = paste(format(df_world$active[1], big.mark = ","), " (",
                       round(100 * df_world$active[1] / df_world$confirmed[1], 1), 
                       "%)", sep = ""), 
         caption = "Active Cases", icon = "fas fa-ambulance", 
         color = active_color)
```

### recovered {.value-box}

```{r}
valueBox(value = paste(format(df_world$recovered[1] , big.mark = ","), " (",
                       round(100 * df_world$recovered[1] / df_world$confirmed[1], 1), 
                       "%)", sep = ""), 
         caption = "Recovered Cases", icon = "fas fa-heartbeat", 
         color = recovered_color)
```

### death {.value-box}

```{r}

valueBox(value = paste(format(df_world$death[1] , big.mark = ","), " (",
                       round(100 * df_world$death[1] / df_world$confirmed[1], 1), 
                       "%)", sep = ""),
         caption = "Death Cases", 
         icon = "fas fa-heart-broken", 
         color = death_color)
```


Row {.tabset}
-----------------------------------------------------------------------

### Cases Distribution by Type (`r  max(df$date)`)

```{r daily_summary}


plotly::plot_ly(
  data = df_tree %>% dplyr::filter(type == "Confirmed"),
  type= "treemap",
  values = ~total,
  labels= ~ country,
  parents=  ~type,
  domain = list(column=0),
  name = "Confirmed",
  textinfo="label+value+percent parent"
) %>%
  plotly::add_trace(
    data = df_tree %>% dplyr::filter(type == "Active"),
    type= "treemap",
    values = ~total,
    labels= ~ country,
    parents=  ~type,
    domain = list(column=1),
    name = "Active",
    textinfo="label+value+percent parent"
  ) %>%
  plotly::add_trace(
    data = df_tree %>% dplyr::filter(type == "Recovered"),
    type= "treemap",
    values = ~total,
    labels= ~ country,
    parents=  ~type,
    domain = list(column=2),
    name = "Recovered",
    textinfo="label+value+percent parent"
  ) %>%
  plotly::add_trace(
    data = df_tree %>% dplyr::filter(type == "Death"),
    type= "treemap",
    values = ~total,
    labels= ~ country,
    parents=  ~type,
    domain = list(column=3),
    name = "Death",
    textinfo="label+value+percent parent"
  ) %>%
  plotly::layout(grid=list(columns=4, rows=1))
  

  


```

### Daily Cumulative Cases
    
```{r}
plotly::plot_ly(data = df_daily,
                x = ~ date,
                y = ~ active_cum, 
                name = 'Active', 
                fillcolor = active_color,
                type = 'scatter',
                mode = 'none', 
                stackgroup = 'one') %>%
  plotly::add_trace(y = ~ recovered_cum,
                    name = "Recovered",
                    fillcolor = recovered_color) %>%
  plotly::add_trace(y = ~ death_cum,
                    name = "Death",
                    fillcolor = death_color) %>%
  plotly::layout(title = "",
                 yaxis = list(title = "Cumulative Number of Cases"),
                 xaxis = list(title = "Date",
                              type = "date"),
                 legend = list(x = 0.1, y = 0.9),
                 hovermode = "compare")

```




### Recovery/Death Ratio

```{r}
df %>% 
  
  dplyr::group_by(country, type) %>%
  dplyr::summarise(total_cases = sum(cases)) %>%
  tidyr::pivot_wider(names_from = type, values_from = total_cases) %>%
  dplyr::arrange(- confirmed) %>%
  dplyr::filter(confirmed >= 20000) %>%
  dplyr::mutate(recover_rate = recovered / confirmed,
                death_rate = death / confirmed) %>% 
  dplyr::mutate(recover_rate = dplyr::if_else(is.na(recover_rate), 0, recover_rate),
                death_rate = dplyr::if_else(is.na(death_rate), 0, death_rate)) %>%
  dplyr::ungroup() %>%
  dplyr::mutate(confirmed_normal = as.numeric(confirmed) / max(as.numeric(confirmed))) %>%
  plotly::plot_ly(y = ~ round(100 * recover_rate, 1),
                  x = ~ round(100 * death_rate, 1),
                  size = ~  log(confirmed),
                  sizes = c(5, 70),
                  type = 'scatter', mode = 'markers',
                  color = ~ country,
                  marker = list(sizemode = 'diameter' , opacity = 0.5),
                  hoverinfo = 'text',
                  text = ~paste("
", country, "
Confirmed Cases: ", confirmed, "
Recovery Rate: ", paste(round(100 * recover_rate, 1), "%", sep = ""), "
Death Rate: ", paste(round(100 * death_rate, 1), "%", sep = "")) ) %>% plotly::layout(title = "Recovery / Death Ratio (Countries with More than 20,000 Cases)", yaxis = list(title = "Recovery Rate", ticksuffix = "%"), xaxis = list(title = "Death Rate", ticksuffix = "%", dtick = 1, tick0 = 0), hovermode = "compare") ``` ### Map ```{r} # map tab added by Art Steinmetz library(leaflet) library(leafpop) library(dplyr) library(purrr) cv_data_for_plot <- df %>% filter(cases > 0) %>% group_by(country,province,lat,long,type) %>% summarise(cases = sum(cases)) %>% mutate(log_cases = 2 * log(cases)) %>% ungroup() cv_data_for_plot.split <- cv_data_for_plot %>% split(cv_data_for_plot$type) pal <- colorFactor(c("orange", "red","green"), domain = c("confirmed", "death","recovered")) map_object <- leaflet() %>% addProviderTiles(providers$Stamen.Toner) names(cv_data_for_plot.split) %>% purrr::walk( function(df) { map_object <<- map_object %>% addCircleMarkers(data=cv_data_for_plot.split[[df]], lng=~long, lat=~lat, # label=~as.character(cases), color = ~pal(type), stroke = FALSE, fillOpacity = 0.8, radius = ~log_cases, popup = leafpop::popupTable(cv_data_for_plot.split[[df]], feature.id = FALSE, row.numbers = FALSE, zcol=c("type","cases","country","province")), group = df, # clusterOptions = markerClusterOptions(removeOutsideVisibleBounds = F), labelOptions = labelOptions(noHide = F, direction = 'auto')) }) map_object %>% addLayersControl( overlayGroups = names(cv_data_for_plot.split), options = layersControlOptions(collapsed = FALSE) ) ``` ### Data ```{r} df_rates <- df_tree %>% dplyr::filter(type != "Active") %>% tidyr::pivot_wider(names_from = "type", values_from = "total") %>% dplyr::mutate(recovery_rate = Recovered / Confirmed, death_rate = Death / Confirmed) bar_chart <- function(label, width = "100%", height = "14px", fill = "#00bfc4", background = NULL) { bar <- htmltools::div(style = list(background = fill, width = width, height = height)) chart <- htmltools::div(style = list(flexGrow = 1, marginLeft = "6px", background = background), bar) htmltools::div(style = list(display = "flex", alignItems = "center"), label, chart) } reactable::reactable(df_rates, pagination = FALSE, highlight = TRUE, height = 800, sortable = FALSE, borderless = TRUE, defaultPageSize = nrow(df_rates), columns = list( country = reactable::colDef(name = "Country", minWidth = 50, maxWidth = 100), Confirmed = reactable::colDef(name = "Confirmed", minWidth = 50, maxWidth = 80), Recovered = reactable::colDef(name = "Recovered", minWidth = 50, maxWidth = 100), Death = reactable::colDef(name = "Death", minWidth = 50, maxWidth = 100), recovery_rate = reactable::colDef(name = "Recovery Rate", minWidth = 50, maxWidth = 100, cell = function(value) { width <- paste0(value , "%") # Add thousands separators value <- format(value, big.mark = ",") bar_chart(value, width = width, fill = "green") }, align = "left"), death_rate = reactable::colDef(name = "Death Rate", minWidth = 50, maxWidth = 100, cell = function(value) { width <- paste0(value , "%") # Add thousands separators value <- format(value, big.mark = ",") bar_chart(value, width = width, fill = "red") }, align = "left")) ) ``` ### About **The Coronavirus Dashboard** This Coronavirus dashboard provides an overview of the 2019 Novel Coronavirus COVID-19 (2019-nCoV) epidemic. This dashboard is built with R using the Rmakrdown framework and can easily reproduce by others. The code behind the dashboard available [here](https://github.com/RamiKrispin/coronavirus_dashboard) **Data** The input data for this dashboard is the [coronavirus](https://github.com/RamiKrispin/coronavirus) R package (dev version). The data and dashboard is refreshed on a daily bases. The raw data pulled from the Johns Hopkins University Center for Systems Science and Engineering (JHU CCSE) Coronavirus [repository](https://github.com/RamiKrispin/coronavirus-csv) **Packages** * Dashboard interface - the [flexdashboard](https://rmarkdown.rstudio.com/flexdashboard/) package. * Visualization - the [plotly](https://plot.ly/r/) package * Data manipulation - [dplyr](https://dplyr.tidyverse.org/), and [tidyr](https://tidyr.tidyverse.org/) * Tables - the [DT](https://rstudio.github.io/DT/) package **Deployment and reproducibly** The dashboard was deployed to Github docs. If you wish to deploy and/or modify the dashboard on your Github account, you can apply the following steps: * Fork the dashboard [repository](https://github.com/RamiKrispin/coronavirus_dashboard), or * Clone it and push it to your Github package * Here some general guidance about deployment of flexdashboard on Github page - [link](https://github.com/pbatey/flexdashboard-example) For any question or feedback, you can either open an [issue](https://github.com/RamiKrispin/coronavirus_dashboard/issues) or contact me on [Twitter](https://twitter.com/Rami_Krispin). Test ======================================================================= Row {data-width=400} ----------------------------------------------------------------------- ### Recovery and Death Rates by Country ```{r} df_summary <-df %>% # dplyr::filter(country != "Others") %>% dplyr::group_by(country, type) %>% dplyr::summarise(total_cases = sum(cases)) %>% tidyr::pivot_wider(names_from = type, values_from = total_cases) %>% dplyr::arrange(- confirmed) %>% dplyr::filter(confirmed >= 25) %>% dplyr::select(country, confirmed, recovered, death) %>% dplyr::mutate(recover_rate = recovered / confirmed, death_rate = death / confirmed) df_summary %>% DT::datatable(rownames = FALSE, colnames = c("Country", "Confirmed", "Recovered", "Death", "Recovery Rate", "Death Rate"), options = list(pageLength = nrow(df_summary), dom = 'tip')) %>% DT::formatPercentage("recover_rate", 2) %>% DT::formatPercentage("death_rate", 2) ``` Daily Trend ======================================================================= Column {data-width=400} ------------------------------------- ### New Cases - Top 15 Countries (`r max(df$date)`) ```{r} max_date <- max(df$date) df %>% dplyr::filter(type == "confirmed", date == max_date) %>% dplyr::group_by(country) %>% dplyr::summarise(total_cases = sum(cases)) %>% dplyr::arrange(-total_cases) %>% dplyr::mutate(country = factor(country, levels = country)) %>% dplyr::ungroup() %>% dplyr::top_n(n = 15, wt = total_cases) %>% plotly::plot_ly(x = ~ country, y = ~ total_cases, text = ~ total_cases, textposition = 'auto', type = "bar") %>% plotly::layout(yaxis = list(title = "Number of Cases"), xaxis = list(title = ""), margin = list( l = 10, r = 10, b = 10, t = 10, pad = 2 )) ``` ### Daily New Cases - China vs. Rest of the World ```{r} ``` Column {data-width=600} ------------------------------------- ### Recovery and Death Rates for Countries with at Least 20000 Cases ```{r} df %>% dplyr::group_by(country, type) %>% dplyr::summarise(total_cases = sum(cases)) %>% tidyr::pivot_wider(names_from = type, values_from = total_cases) %>% dplyr::arrange(- confirmed) %>% dplyr::filter(confirmed >= 20000) %>% dplyr::mutate(recover_rate = recovered / confirmed, death_rate = death / confirmed) %>% dplyr::mutate(recover_rate = dplyr::if_else(is.na(recover_rate), 0, recover_rate), death_rate = dplyr::if_else(is.na(death_rate), 0, death_rate)) %>% dplyr::ungroup() %>% dplyr::mutate(confirmed_normal = as.numeric(confirmed) / max(as.numeric(confirmed))) %>% plotly::plot_ly(y = ~ round(100 * recover_rate, 1), x = ~ round(100 * death_rate, 1), size = ~ log(confirmed), sizes = c(5, 70), type = 'scatter', mode = 'markers', color = ~ country, marker = list(sizemode = 'diameter' , opacity = 0.5), hoverinfo = 'text', text = ~paste("
", country, "
Confirmed Cases: ", confirmed, "
Recovery Rate: ", paste(round(100 * recover_rate, 1), "%", sep = ""), "
Death Rate: ", paste(round(100 * death_rate, 1), "%", sep = "")) ) %>% plotly::layout(yaxis = list(title = "Recovery Rate", ticksuffix = "%"), xaxis = list(title = "Death Rate", ticksuffix = "%", dtick = 1, tick0 = 0), hovermode = "compare") ``` ### Cases Status Update for `r max(df$date)` ```{r} daily_summary <- df %>% dplyr::filter(date == max(date)) %>% dplyr::group_by(country, type) %>% dplyr::summarise(total = sum(cases)) %>% tidyr::pivot_wider(names_from = type, values_from = total) %>% dplyr::arrange(-confirmed) %>% dplyr::select(country = country, confirmed, recovered, death) DT::datatable(data = daily_summary, rownames = FALSE, colnames = c("Country", "Confirmed", "Recovered", "Death"), options = list(pageLength = nrow(daily_summary), dom = 'tip')) ``` Data ======================================================================= ```{r} df %>% dplyr::select(Date = date, Province = province, Country = country, `Case Type` = type, `Number of Cases` = cases) %>% DT::datatable(rownames = FALSE, options = list(searchHighlight = TRUE, pageLength = 20), filter = 'top') ```